package com.fencing_squad.homo.page;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fencing_squad.homo.ResourceTable;
import com.fencing_squad.homo.list.Tip;
import com.fencing_squad.homo.list.TipProvider;
import com.fencing_squad.homo.map_util.bean.InputTipsResult;
import com.fencing_squad.homo.map_util.map.*;
import com.fencing_squad.homo.map_util.util.MapUtils;
import com.fencing_squad.homo.map_util.util.PermissionsUtils;
import com.fencing_squad.homo.util.AnimationConfig;
import com.fencing_squad.homo.util.CustomComponent;
import com.fencing_squad.homo.util.Data;
import com.fencing_squad.homo.util.Network;
import com.fencing_squad.homo.util.function.FunctionInt;
import com.fencing_squad.homo.util.function.FunctionVoid;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.agp.components.*;
import ohos.agp.window.dialog.CommonDialog;
import ohos.app.Context;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.photokit.metadata.AVStorage;
import ohos.multimodalinput.event.TouchEvent;
import ohos.security.SystemPermission;
import ohos.utils.net.Uri;

import java.io.FileDescriptor;
import java.io.InputStream;
import java.util.Base64;
import java.util.List;

public class Offer {
    private Component offer = null;

    private NavMap navMap;

    private MapDataHelper mapDataHelper;

    private Context context;

    private String keyword = "";

    private Tip start;

    private Tip stop;

    private boolean isStart = true;

    private String startRough = "";

    private String startDetail = "";

    private String stopRough = "";

    private String stopDetail = "";

    private TipProvider tipProvider;

    private Text editOffer = null;

    private Text editStart = null;

    private Text editStop = null;

    private Component search = null;

    private Component offerInput = null;

    private byte[] img = null;

    private CommonDialog window = null;

    private String offerContent = "";

    private String type = "购物";

    private String level = "海外";

    private final String[] offerType = new String[] {"购物", "取件", "送件", "打印", "签字", "组队"};

    private final String[] offerLevel = new String[] {"海外", "室外", "公共场所", "教学楼", "办公楼", "寝室楼"};

    private double money = 0;

    private final double rate = 100;

    private Text moneyDisplay = null;

    private boolean fold = true;

    private boolean editable = false;

    private TextField textRough;

    private TextField textDetail;

    private FunctionVoid redirectToLogin;

    public Offer() {
    }

    public Component get(Context context, FunctionInt imageFunc, FunctionVoid redirectToLogin) {
        this.context = context;
        this.redirectToLogin = redirectToLogin;
        if(offer == null) {
            offer = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_offer, null, false);
        }
        offerInput = offer.findComponentById(ResourceTable.Id_offerInput);
        search = offer.findComponentById(ResourceTable.Id_search);
        moneyDisplay = (Text) offer.findComponentById(ResourceTable.Id_money);
        Button offerSubmit = (Button) offer.findComponentById(ResourceTable.Id_offerSubmit);
        ListContainer listContainer = (ListContainer) offer.findComponentById(ResourceTable.Id_inputTips);
        tipProvider = new TipProvider(context);
        listContainer.setItemProvider(tipProvider);
        // 防止与map滑动事件冲突***
        listContainer.setTouchEventListener((component, touchEvent) -> true);
        // 设置提示点击事件
        listContainer.setItemClickedListener(new ListContainer.ItemClickedListener() {
            @Override
            public void onItemClicked(ListContainer listContainer, Component component, int i, long l) {
                String[] raw_locations = null;
                if (isStart) {
                    start = (Tip) tipProvider.getItem(i);
                    startRough = start.getName();
                    raw_locations = start.getLocation().split(",");
                }
                else {
                    stop = (Tip) tipProvider.getItem(i);
                    stopRough = stop.getName();
                    raw_locations = stop.getLocation().split(",");
                }
                listContainer.setVisibility(Component.HIDE);
                double[] locations = new double[2];
                try{
                    locations[0] = Double.parseDouble(raw_locations[0]);
                    locations[1] = Double.parseDouble(raw_locations[1]);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mapDataHelper.removeAllElements();
                mapDataHelper.setMapCenter(locations[0], locations[1], isStart ? 1 : 2);
            }
        });

        final int[] initial = {0, 0};
        VelocityDetector detector = VelocityDetector.obtainInstance();
        offerInput.setTouchEventListener(new Component.TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                int top = offerInput.getTop();
                int index = touchEvent.getIndex();
                int y = (int) touchEvent.getPointerScreenPosition(index).getY();
                detector.addEvent(touchEvent);
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
                    if (index == -1) {
                        return true;
                    }
                    initial[1] = initial[0] = y;
                }
                else if (touchEvent.getAction() == TouchEvent.POINT_MOVE) {
                    if(index != -1) {
                        int delta = y - initial[1];
                        if (top >= 1920 && delta > 0) {
                            return true;
                        }
                        else if (top <= 500 && delta < 0) {
                            return true;
                        }
                        offerInput.setTop(offerInput.getTop() + y - initial[1]);
                        initial[1] = y;
                    }
                }
                else if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    detector.calculateCurrentVelocity(1000, 22000, 22000);
                    int speed = (int) detector.getVerticalVelocity();//获得当前的滑动速度
                    int delta = y - initial[0];//获取手指滑动距离
                    if ( top < 490 || fold && (speed > 1200 || delta < -300) || !fold && (speed <= 1200 && delta <= 300)) {
                        AnimationConfig.getOfferInputShowAnim(offerInput).start();
                        fold = false;
                    }
                    else if ( top > 1920 || !fold && (speed > 1200 || delta > 300) || fold && (speed <= 1200 && delta >= -300)) {
                        AnimationConfig.getOfferInputHideAnim(offerInput).start();
                        fold = true;
                    }
                }
                return true;
            }
        });

        textRough = (TextField) offer.findComponentById(ResourceTable.Id_searchInput);
        textRough.addTextObserver(new Text.TextObserver() {
            @Override
            public void onTextUpdated(String s, int i, int i1, int i2) {
                if (editable) {
                    listContainer.setVisibility(Component.VISIBLE);
                    keyword = s;
                    mapDataHelper.getInputTips(keyword);
                }
            }
        });

        textDetail = (TextField) offer.findComponentById(ResourceTable.Id_detailInput);
        textDetail.addTextObserver(new Text.TextObserver() {
            @Override
            public void onTextUpdated(String s, int i, int i1, int i2) {
                if (editable) {
                    if (isStart) {
                        startDetail = s;
                    }
                    else {
                        stopDetail = s;
                    }
                }
            }
        });

        offer.findComponentById(ResourceTable.Id_confirm).setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                System.out.println(startRough);
                System.out.println(startDetail);
            }
        });

        Slider offerMoney = (Slider) offer.findComponentById(ResourceTable.Id_offerMoney);

        offerMoney.setValueChangedListener(new Slider.ValueChangedListener() {
            @Override
            public void onProgressUpdated(Slider slider, int i, boolean b) {
                money = i / rate;
                moneyDisplay.setText(String.valueOf(money));
            }

            @Override
            public void onTouchStart(Slider slider) {}

            @Override
            public void onTouchEnd(Slider slider) {}
        });

        offerMoney.setTouchEventListener(((component, touchEvent) -> true));

        Picker offerLevel = (Picker) offer.findComponentById(ResourceTable.Id_offerLevel);

        offerLevel.setTouchEventListener((component, touchEvent) -> true);

        offerLevel.setDisplayedData(this.offerLevel);

        offerLevel.setValueChangedListener((picker, oldVal, newVal) -> {
            level = this.offerLevel[newVal];
        });

        Picker offerType = (Picker) offer.findComponentById(ResourceTable.Id_offerType);

        offerType.setTouchEventListener((component, touchEvent) -> true);

        offerType.setDisplayedData(this.offerType);

        offerType.setValueChangedListener((picker, oldVal, newVal) -> {
            type = this.offerType[newVal];
        });

        Offer self = this;

        editOffer = (Text) offer.findComponentById(ResourceTable.Id_editOffer);

        editOffer.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                AnimationConfig.getOfferInputShowAnim(offerInput).start();
                fold = false;
                window = CustomComponent.getNewPost(context, 1, self::editText, imageFunc, self::onTextSubmit, self::clear);
                window.show();
            }
        });

        editStart = (Text) offer.findComponentById(ResourceTable.Id_editStart);
        editStop = (Text) offer.findComponentById(ResourceTable.Id_editStop);

        editStart.setClickedListener(component -> {
            isStart = true;
            editable = true;
            offerInput.setVisibility(Component.HIDE);
            search.setVisibility(Component.VISIBLE);
        });

        editStop.setClickedListener(component -> {
            isStart = false;
            editable = true;
            offerInput.setVisibility(Component.HIDE);
            search.setVisibility(Component.VISIBLE);
        });

        Component back = offer.findComponentById(ResourceTable.Id_back);
        back.setClickedListener(component -> {
            search.setVisibility(Component.HIDE);
            offerInput.setVisibility(Component.VISIBLE);
            back();
        });

        Component confirm = offer.findComponentById(ResourceTable.Id_confirm);
        confirm.setClickedListener(component -> {
            if (isStart) {
                editStart.setText(startRough + " " + startDetail);
            }
            else {
                editStop.setText(stopRough + " " + stopDetail);
            }
            search.setVisibility(Component.HIDE);
            offerInput.setVisibility(Component.VISIBLE);
            back();
        });

        offerSubmit.setClickedListener(component ->  {
            if (!Data.Account.isLogin) {
                this.redirectToLogin.func();
                return;
            }
            if (!check()) {
                CustomComponent.getDialog(context, "请输入完整内容", null, null).show();
                return;
            }
            JSONObject object = new JSONObject();
            object.put("content", offerContent);
            object.put("from_pos", start.getLocation());
            object.put("from_detail", startRough + " " + startDetail);
            object.put("to_pos", stop.getLocation());
            object.put("to_detail", stopRough + " " + stopDetail);
            object.put("type", type);
            object.put("level", level);
            object.put("has_award", !(money <= 0));
            object.put("money", money);
            if (img != null) {
                JSONArray jsonArray = new JSONArray();
                jsonArray.add(Base64.getEncoder().encodeToString(img));
                object.put("image_streams", jsonArray);
            }
            mapDataHelper.getDistance(start.getLocation(), stop.getLocation(), (distance) -> {
                object.put("distance", distance);
                Network.postJson("/reward", object.toJSONString(), this::postOfferResolve, this::reject);
                System.out.println(object);
            });
        });

        if (offer.findComponentById(ResourceTable.Id_map) instanceof NavMap) {
            navMap = (NavMap) offer.findComponentById(ResourceTable.Id_map);
            navMap.setDrawPath(false);
        }

        initMap();
        return offer;
    }

    private void postOfferResolve(JSONObject object) {
        System.out.println(object);
        clearAll();
    }

    private void reject(int code, String message) {
        if(code == 404) {
            CustomComponent.getDialog(context, message, null, null).show();
        }
        else {
            System.out.println(message);
        }
    }

    private void clearAll() {
        clear();
        stopDetail = "";
        stopRough = "";
        editStop.setText("");
        startDetail = "";
        startRough = "";
        editStart.setText("");
        start = null;
        stop = null;
    }

    private void clear() {
        offerContent = "";
        img = null;
        editOffer.setText("");
    }

    private void initMap() {
        mapDataHelper = new MapDataHelper(navMap, context);

        PermissionsUtils permissionsUtils = PermissionsUtils.getInstance();

        // 监听地理位置权限的获取，获取后开始定位
        permissionsUtils.setRequestListener(permission -> {
            System.out.println(permission);
            if (permission.equals(SystemPermission.LOCATION)) {
                mapDataHelper.getMyLocation();
                System.out.println("location got");
            }
        });

        Offer self = this;

        mapDataHelper.setDataCallBack(new MapDataHelper.DataCallBack() {
            @Override
            public void setInputTipsView(List<InputTipsResult.TipsEntity> tips) {
                self.setInputTips(tips);
            }

            @Override
            public void setRouteView(String route) {}
        });
    }

    private void setInputTips(List<InputTipsResult.TipsEntity> tips) {
        tipProvider.clearAll();
        for(InputTipsResult.TipsEntity tip : tips) {
            try {
                Tip tip_temp = new Tip();
                tip_temp.setAddress((String) tip.getAddress());
                tip_temp.setLocation(tip.getLocation());
                tip_temp.setName(tip.getName());
                tipProvider.append(tip_temp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void setImageURI(String value) {
        //定义数据能力帮助对象
        DataAbilityHelper helper = DataAbilityHelper.creator(context);
        //定义图片来源对象
        ImageSource imageSource = null;
        //获取选择的Img对应的Id
        String chooseImgId = null;
        //如果是选择文件则getUriString结果为content://com.android.providers.media.documents/document/image%3A30，其中%3A是":"的URL编码结果，后面的数字就是image对应的Id
        //如果选择的是图库则getUriString结果为content://media/external/images/media/30，最后就是image对应的Id
        //这里需要判断是选择了文件还是图库
        if(value.lastIndexOf("%3A")!=-1){
            chooseImgId = value.substring(value.lastIndexOf("%3A")+3);
        }
        else {
            chooseImgId = value.substring(value.lastIndexOf('/')+1);
        }
        //获取图片对应的uri，由于获取到的前缀是content，我们替换成对应的dataability前缀
        Uri uri = Uri.appendEncodedPathToUri(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI,chooseImgId);
        try {
            //读取图片
            FileDescriptor fd = helper.openFile(uri, "r");
            imageSource = ImageSource.create(fd, null);
            //创建位图
            PixelMap pixelMap = imageSource.createPixelmap(null);

            CustomComponent.addImage(window, pixelMap);

            InputStream in = helper.obtainInputStream(uri);
            img = new byte[in.available()];
            System.out.println(in.available());
            in.read(img);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (imageSource != null) {
                imageSource.release();
            }
        }
    }

    public void editText(String text) {
        offerContent = text;
    }

    public void onTextSubmit() {
        if (window != null) {
            window.hide();
        }
        editOffer.setText(offerContent);
    }

    public void mapReload() {
        if (mapDataHelper != null) {
            mapDataHelper.mapReload();
        }
    }

    public void loadMap() {
        if (mapDataHelper != null) {
            mapDataHelper.getMyLocation();
        }
    }

    public double[] str2Mercator (String location) {
        double[] locator = str2Locator(location);
        return MapUtils.lonLat2Mercator(locator[0], locator[1]);
    }

    public double[] str2Locator (String location) {
        String[] raw_locations = location.split(",");
        double[] locations = new double[2];
        try{
            locations[0] = Double.parseDouble(raw_locations[0]);
            locations[1] = Double.parseDouble(raw_locations[1]);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return locations;
    }

    private void back() {
        navMap.clearElements();
        if (start != null) {
            double[] locator = str2Locator(start.getLocation());
            mapDataHelper.setMapCenter(locator[0], locator[1], -1);
            mapDataHelper.addElementToMap(str2Mercator(start.getLocation()), Config.ROUTE_START, "", true);
        }
        if (stop != null) {
            mapDataHelper.addElementToMap(str2Mercator(stop.getLocation()), Config.ROUTE_END, "", true);
        }
        if (start == null && stop == null) {
            mapDataHelper.getMyLocation();
        }
        editable = false;
        textRough.setText("");
        textDetail.setText("");
    }

    private boolean check() {
        return !offerContent.equals("") && start != null && stop != null;
    }

    private int vp2px(float vp) {
        return AttrHelper.vp2px(vp, context);
    }
}
